iT邦幫忙

2023 iThome 鐵人賽

DAY 8
2

回到開發選用設計模式的起點,我們會希望有幾個目標可以被滿足:

  • 減少重複的程式碼
  • 減少出錯的機會
  • 將資料與業務邏輯分離,可以讓兩邊的程式碼更加容易測試
  • 提升程式碼的可讀性

所以在不管選用什麼模式之前,專案的設計應該要可以符合上面的原則。

在講到為什麼之前,我們先來認識一下 Repository Pattern,這個是來自微軟對於 Repository Pattern 的說明。

Use a repository to separate the logic that retrieves the data and maps it to the entity model from the business logic that acts on the model. The business logic should be agnostic to the type of data that comprises the data source layer. For example, the data source layer can be a database, a SharePoint list, or a Web service.

From: learn.microsoft.com

Repository Pattern 的作法其實完美地實作出了 Dependency inversion principle(DIP) 的作法。

所以在實際使用上,可以這樣完成

# 將 Interface 與我們實作出來的 Repository 綁定
class AppServiceProvider extends ServiceProvider
   public function register(): void
   {
      $this->app->bind(PostRepositoryInterface::class, PostEloquentRepostiory::class);
      $this->app->bind(AuthorRepositoryInterface::class, AuthorManagementRepostiory::class);
   }
}

# 接著我們就可以注入到想要使用的地方
class PostController extends Controller
{

   public function __invoke(PostRepositoryInterface $repostiory)
   {
      // ...
      $data = $repostiory->get();
   }
}

但是為了滿足可抽換的條件,所以 repostiory 實作的方法不能 return Elquent 的 model,否則這會將 repostiory 直接依賴了 Elquent。而且這樣建立出來的 repostiory 也只是包裝過的 Elquent query 而已。

為此把 Elquent 從這邊分離出來,就才能滿足 repostiory 要符合可抽換的特性。

你真的需要?

還記得前面有說到的 YAGNI 嗎? 在開發的過程中應要,盡所能去避免假設未來的功能會需要某種設計模式。使用非預設的工具而且沒有良好文件的輔助時,這都是讓未來專案維護埋下更多的地雷。

Over-engineering 才是殺死眾多專案的維護者的問題。就如以一個專案選用資料庫來說,使用哪一個系列的資料庫的決策通常不太可能說變就變,就算是要變化也會有一定程度的功能上的變動,這樣讓所謂可以直接抽換資料庫的情況或然率接近於不可能會發生。

總是跟不上你的 Repository Pattern

想想看,在產品的第一階段完成後上線。之後 PM 發現需要繼續追加一些功能,例如:

我們實作了一個方法可以列出某個 author 下所有的 posts 的方法 all(),現在老闆看到了一些成功的矽谷公司都開始搞付費內容後,想要開始將 post 分成免費用戶可以閱讀的 post,跟 Premium 會員才可以看得到的 post。
這時候我們開始絞盡腦汁開始要接受這個挑戰,下面是有可能的作法:

  • 新增一個 parameter 給 all() 來區分,像是 bool $isPremium = true
  • 新增一個獨立的方法給免費用戶,像是:allForPremium()
  • 或是直接開一組新的 Repository 給 Premium 會員

如果接下來需求進化成,要給尚未註冊的會員有機會體驗 Premium 功能,所以要可以給訪客看到這些 Premium 會員才看得到的 posts 時你會怎麼作?這會讓你的 Repository 有著如何發展的變化?

這時候才發現到,原來要擴充 Repository 其實有點難度,尤其又要不能在產生 Code smell 的同時兼顧開發功能的步調。最後你會得到巨大的且認知複雜度高的 Repository。

Next step

所以在下一篇中,將會提到幾個在 Laravel 中獨特且有效可以使用的方案,其實你一開始就已經在這卻的道路前進了,只是你還沒發現原來開發可以這麼有條理且又有效率。


上一篇
#6 API Service 的第四步: 在忙也不要忘記加測試
下一篇
#8 你其實不需要在 Laravel 使用 Repository Pattern (2/2)
系列文
Laravel 擴展宇宙:從 1 到 100 十倍速打造產品獨角獸30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
mikehsu0618
iT邦新手 2 級 ‧ 2023-09-23 23:01:46

置板凳/images/emoticon/emoticon16.gif

我要留言

立即登入留言